package com.na.game;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.media.AudioManager;
import android.os.Environment;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;

import com.na.game.GameManager.Clazz;
import com.na.game.data.DataManager;
import com.na.game.event.Event;
import com.na.game.event.EventManager;
import com.na.game.event.impl.KeyEvent;
import com.na.game.event.impl.TouchEvent;
import com.na.game.graphics.Graphics;
import com.na.game.platform.ad.Ad;
import com.na.game.props.PropsManager;
import com.na.game.resource.Destruction;
import com.na.game.resource.ResourceManager;
import com.na.game.sound.SoundManager;
import com.na.game.ui.UI;
import com.na.game.ui.UIManager;
import com.na.game.util.Cache;
import com.na.game.util.GameConfig;
import com.na.game.util.PListManager;
import com.na.game.util.Util;

public class GameMain implements Runnable, OnTouchListener, OnKeyListener, Clazz, Destruction {

	protected boolean running;
	protected Graphics graphics;
	protected float scale = 1.0f;
	protected int screenWidth, screenHeight;
	protected float paintOffsetX, paintOffsetY;
	protected GameActivity context;
	protected AudioManager am;
	protected SurfaceView view;
	
	public GameMain(GameActivity context, SurfaceView view) {
		this.context = context;
		this.view = view;
		Display display = context.getWindowManager().getDefaultDisplay();
		screenWidth = display.getWidth();
		screenHeight = display.getHeight();
		if (screenWidth != GameConfig.STANDARD_WIDTH || screenHeight != GameConfig.STANDARD_HEIGHT) {
			scale = (float) screenWidth / GameConfig.STANDARD_WIDTH;
			float yscale = (float) screenHeight / GameConfig.STANDARD_HEIGHT;
			if (yscale < scale) {
				scale = yscale;
			}
			paintOffsetX = ((screenWidth - GameConfig.STANDARD_WIDTH * scale) / 2);
			paintOffsetY = ((screenHeight - GameConfig.STANDARD_HEIGHT * scale) / 2);
		}
		if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
			GameConfig.SDCARD = Environment.getExternalStorageDirectory();
		}
		GameConfig.DENSITY = context.getResources().getDisplayMetrics().densityDpi;
		am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
		GameManager.init(new EventManager(), new UIManager(), new ResourceManager(),
						context, new PListManager(), new SoundManager(context),
						new PropsManager(context), new DataManager(context), this);
	}

	@Override
	public void run() {
		while (running) {
			long cost = System.currentTimeMillis();
			// main
			GameManager.update();
			repaint();
			// main
			cost = System.currentTimeMillis() - cost;
			if (cost < GameConfig.MSPF) {
				try {
					Thread.sleep(GameConfig.MSPF - cost);
				} catch (InterruptedException e) {
				}
			}
		}
		GameManager.destroy();
		context.finish();
	}
	
	protected void repaint() {
		if (graphics == null) {
			graphics = new Graphics(GameConfig.STANDARD_WIDTH, GameConfig.STANDARD_HEIGHT, context.getGameEntity().invoke(GameEntity.FUNC_GET_DEFAULT_FONT, Typeface.class));
		}
		GameManager.get(UIManager.class).paint(graphics);
		
		SurfaceHolder holder = view.getHolder();
		Canvas canvas = holder.lockCanvas();
		if (canvas != null) {
			graphics.drawBuffer(canvas, paintOffsetX, paintOffsetY, scale);
			holder.unlockCanvasAndPost(canvas);
		}
	}
	
	@Override
	public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
		if (event.getAction() == android.view.KeyEvent.ACTION_DOWN) {
			switch (keyCode) {
				case android.view.KeyEvent.KEYCODE_VOLUME_UP:
					am.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND);
					break;
				case android.view.KeyEvent.KEYCODE_VOLUME_DOWN:
					am.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND);
					break;
			}
		}
		GameManager.get(EventManager.class).addEvent(new KeyEvent(Event.KEY_EVENT, event.getAction(), keyCode));
		return true;
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		int action = event.getAction() & MotionEvent.ACTION_MASK;
		if (action == MotionEvent.ACTION_CANCEL) {
			action = MotionEvent.ACTION_UP;
		}
		GameManager.get(EventManager.class).addEvent(new TouchEvent(Event.TOUCH_EVENT, action, (event.getX() - paintOffsetX) / scale, (event.getY() - paintOffsetY) / scale));
		return true;
	}
	
	public void start() {
		if (!running) {
			running = true;
			GameManager.get(UIManager.class).pushUI(context.getGameEntity().invoke(GameEntity.FUNC_GET_INIT_UI, UI.class));
			new Thread(this).start();
		}
	}
	
	public void stop() {
		running = false;
	}
	
	@Override
	public Class<?> getClazz() {
		return GameMain.class; // use GameMain.class
	}

	@Override
	public void destroy() {
		Ad.getAd().destroy();
		Cache.destroy();
		Util.destroy();
	}
}
